package cn.rengy.auth.jwt;

import cn.base.springutil.util._BeanUtils;
import cn.hutool.core.bean.BeanUtil;
import cn.rengy.auth.entity.principal.Identity;
import com.alibaba.fastjson2.JSONObject;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ClaimsBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.impl.DefaultClaims;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.StringUtils;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Date;
import java.util.Map;

/**
 * 创建token
 */
@Slf4j
public class JwtCreator {
	private static SecretKey 密钥;
	//private static int 有效期=60*60*1000;//token有效期60*60*1000
	//@Value("${jwt.secret}")
	/*2021做为SecureRandom种子，生成后的base64:
	 Ja52xm2YF0aL0HToYaWookA/NsmoPMIEbVULGSQWHzE=
	 可在jwt官网验签*/
    private static final String secret="2021";
    //创建时把clientId映射到aud
    //private static final Map<String,String> fieldMapping=new HashMap<String,String>(2,1);
    //反转
    //private static final Map<String,String> reversedFieldMapping;
	static {
		密钥 =generatorKey();
		//fieldMapping.put("clientId", "aud");//代表这个JWT的接收对象
		//fieldMapping.put("userId", "sub");//代表这个JWT的主体，即它的所有人
		
		//reversedFieldMapping=MapUtil.reverse(fieldMapping);
	}


	/*static {
		String SECRET_KEY="de98550ef004da097283a6b3b266c1db440223ebeb0db42c4fea026870c6b71f";
		byte keyBytes []=null;
		try {
			keyBytes=Hex.decodeHex(SECRET_KEY);
		} catch (DecoderException e) {
			logger.error(e.getMessage());
		}
		密钥 = Keys.hmacShaKeyFor(keyBytes);
	}*/
	/*public static Key getKey() {
		return 密钥;
	}*/

	public static String createToken(Claims claims, Identity identity) {//, Duration timeout
		ClaimsBuilder claimsBuilder= Jwts.claims();
		if(claims!=null){
			claimsBuilder.add(claims);
		}
		//String jti=RandomStringUtils.randomAlphanumeric(32);
		//long currentTimeMillis = System.currentTimeMillis();
		claimsBuilder
				//.setId(jti)
				//.setAudience(identity.getClientId())
				.issuedAt(new Date())//签发时间
		//.setExpiration(new Date(currentTimeMillis+timeout.toMillis()))//过期时间
		;
		if(identity!=null){

			Map<String,Object> beanMap=BeanUtil.beanToMap(identity,false,true);
			beanMap.put("@class", identity.getClass().getName());
			claimsBuilder.add("identity",beanMap);

			//String sub=AES.encryptHex(userid.toString(), GlobalSystemKey.key);
			//String sub=identity.getName();
//			claimsBuilder.add("class", identity.getClass().getName());
//			Map<String,Object> beanMap=new HashMap<String,Object>();

//			BeanUtil.beanToMap(identity, beanMap, false, new Editor<String>() {
//				@Override
//				public String edit(String key){
//					String value=fieldMapping.get(key);
//					return value==null ? key : value;
//				}
//			});


//			CopyOptions copyOptions=CopyOptions.create()
//					.setIgnoreNullValue(true)//忽略空值，不忽略后面build时也加不进去空值
//					.setFieldMapping(fieldMapping).setFieldValueEditor(new BiFunction<String, Object, Object>() {
//						//简便写法 setFieldValueEditor((fieldName, fieldValue) -> fieldValue.toString());
//						@Override
//						public Object apply(String fieldName, Object fieldValue) {
//							if(fieldValue==null){
//								return null;
//							}else{
//								if(fieldName.equals("sub")){//sub对应的userId是Long类型，保存报错
//									return fieldValue.toString();
//								}
//							}
//							return fieldValue;
//						}
//					});
//			BeanUtil.beanToMap(identity, beanMap,copyOptions);
//			claimsBuilder.add(beanMap);//ParameterMap中强制删除了空值的key


		}
		return JwtUtils.create(claimsBuilder.build(), 密钥);
	}
//	public static String createToken(Identity identity) {//, Duration timeout
//		//String jti=RandomStringUtils.randomAlphanumeric(32);
//		//String sub=AES.encryptHex(userid.toString(), GlobalSystemKey.key);
//		//String sub=identity.getName();
//		DefaultClaims defaultClaims=new DefaultClaims();
//		defaultClaims.put("class", identity.getClass().getName());
//		//defaultClaims.putAll(_BeanUtils.bean2Map(identity));
//		//defaultClaims.remove("name");
//		//defaultClaims.remove("clientId");
//		BeanUtil.beanToMap(identity, defaultClaims, false, new Editor<String>() {
//			@Override
//			public String edit(String key){
//				String value=fieldMapping.get(key);
//				return value==null ? key : value;
//			}
//		});
//		long currentTimeMillis = System.currentTimeMillis();
//		defaultClaims
//		//.setId(jti)
//		//.setAudience(identity.getClientId())
//		.setIssuedAt(new Date(currentTimeMillis))//签发时间
//		//.setExpiration(new Date(currentTimeMillis+timeout.toMillis()))//过期时间
//		;
//		return JwtUtils.create(defaultClaims, 密钥);
//	}
	/*public static String createRefreshToken(Identity identity,Duration timeout) {
		String token=RandomStringUtils.randomAlphanumeric(32);
		return token;
	}*/
	
	
	
	public static Identity parseToken(String jwt) {
		Claims claims=JwtUtils.verify(jwt, 密钥);
		Map beanMap=claims.get("identity",Map.class);
		if(beanMap!=null){
			String className=(String)beanMap.remove("@class");
			//log.debug("className={}",className);
			Identity identity= _BeanUtils.createInstance(className,Identity.class);
			return BeanUtil.fillBeanWithMap(beanMap,identity,null);
			//CopyOptions copyOptions=CopyOptions.create()
			//		.setFieldMapping(reversedFieldMapping);
			//return BeanUtil.fillBeanWithMap(claims, identity, copyOptions);
		}
		return null;
	}

	/**
	 * 不验签，仅解析Payload
	 * @param jwt
	 * @return
	 */
	public static Claims parsePayload(String jwt) {
		String payload=new String(Base64.decodeBase64(jwt.split("\\.")[1])) ;
		DefaultClaims claims=new DefaultClaims(JSONObject.parseObject(payload,Map.class));
		return claims;
	}
	
	
	private static SecretKey generatorKey() {
		KeyGenerator kgen;
		try {
			kgen = KeyGenerator.getInstance("HmacSHA256");
			SecureRandom secureRandom=SecureRandom.getInstance("SHA1PRNG");
			secureRandom.setSeed(StringUtils.getBytesUtf8(secret));
			kgen.init(256, secureRandom);
			//SecretKey secretKey= kgen.generateKey();
			return kgen.generateKey();
			//String str=Base64.encodeBase64String(secretKey.getEncoded());
			//System.out.println(str);
			//使用SecureRandom生成密钥不是secret，要使用secret做为key直接用 Key key =new SecretKeySpec(secret, "HmacSHA256");

		} catch (NoSuchAlgorithmException e) {
			log.error("NoSuchAlgorithmException");
			throw new RuntimeException(e);
		}
	}
	
	
	
	
	/*@SuppressWarnings("unused")
	private void generateSecretKey() throws NoSuchAlgorithmException {
		MD2 
		MD5 
		SHA-1
		 SHA-224
		 SHA-256
		 SHA-384
		 SHA-512
		MessageDigest md= MessageDigest.getInstance("SHA-256");
		md.update("distribution-catering+www.uniontrip.com".getBytes());
		byte by[]=md.digest();
		String s=Hex.encodeHexString(by);
		//de98550ef004da097283a6b3b266c1db440223ebeb0db42c4fea026870c6b71f
		//common 工具类
		//String s=DigestUtils.sha256Hex("distribution-catering+www.uniontrip.com");
		String b=Base64.encodeBase64String(by);
	}*/
	/*public static void main(String args[]) {
		//String s=DigestUtils.sha256Hex("distribution-catering+www.uniontrip.com"); 
		//System.out.println(s);
		String className=LocalIdentity.class.getName();
		System.out.println(className);
		Identity identity=_BeanUtils.createInstance(className,Identity.class);
		identity.setUserid(1L);
		System.out.println(identity);
		
		LocalIdentity localIdentity=new LocalIdentity();
		localIdentity.setUlid(10l);
		localIdentity.setUserid(20l);
		Map<String, Object> map=_BeanUtils.bean2Map(localIdentity);
		System.out.println(map);
		
		_BeanUtils.map2Bean(map, identity);
		System.out.println(identity);
		
		String token=createToken(localIdentity,Duration.ofDays(1));
		System.out.println(token);
	}*/
}
